from six import moves

from odoo import api, models, fields, _
from datetime import datetime
from odoo.exceptions import ValidationError, UserError
from collections import defaultdict
from odoo.tools.float_utils import float_compare, float_round


class StockPicking(models.Model):
    _inherit = 'stock.picking'

    """自动临期质检
    1、全部lot，有库存、配置有效期
    2、查询内部位置quant
    3、根据quant位置生成临期质检调拨
    4、查询目前没有完成质检的调拨单、质检单
    5、完成质检之后生成回调、以及报废调拨单（所有报废都要审批）
    """

    @api.depends('picking_type_id', 'location_id', 'location_dest_id')
    def _compute_quality_check(self):
        """临期质检报废、临期质检入库"""
        for rec in self:
            if rec.picking_type_id.barcode == 'WTT-EQ' and rec.location_id == self.env.ref('sb_quality_check.location_quality_check'):
                rec.sb_is_quality_check = True
            else:
                rec.sb_is_quality_check = False

            if rec.location_dest_id.usage == 'inventory' and rec.location_dest_id.scrap_location:
                rec.sb_loss_approve = True
            else:
                rec.sb_loss_approve = False

    @api.depends('sb_workflow_ids')
    def _compute_sb_workflow_ids_sum(self):
        for item in self:
            if item.sb_workflow_ids:
                item.sb_workflow_ids_sum = len(item.sb_workflow_ids)
            else:
                item.sb_workflow_ids_sum = 0

    @api.depends('picking_type_id', 'location_id', 'location_dest_id', 'state')
    def _compute_sb_required_iqc(self):
        """原材料入库质检"""
        for rec in self:
            sb_required_iqc = True if rec.move_ids.mapped('product_id').filtered(lambda x: x.s_required_iqc) else False
            if rec.check_ids and rec.check_ids.filtered(lambda x: x.quality_state != 'fail'):
                rec.sb_required_iqc = False
            elif sb_required_iqc and rec.picking_type_id and rec.picking_type_id.barcode == 'WTT-RECEIPTS':
                rec.sb_required_iqc = True
            else:
                rec.sb_required_iqc = False

    def _default_workflow_template(self):
        if self.sb_is_quality_check:
            return self.env.ref('sb_quality_check.workflow_data_quality_check').id
        return

    sb_workflow_template_id = fields.Many2one('sb.workflow.template', string="Approval Workflow Template",
                                              domain="[('sb_workflow_template_item_ids', '!=', False),"
                                                     "('workflow_type', '=', 'stock_picking')]", default=_default_workflow_template)

    sb_workflow_id = fields.Many2one('sb.workflow', string="Current Approval Workflow", copy=False)
    sb_workflow_state = fields.Selection(related="sb_workflow_id.state", readonly=True, string="Approval Status",
                                         store=True)
    sb_workflow_item_ids = fields.One2many(related="sb_workflow_id.sb_workflow_item_ids", string="Approval Items")
    sb_workflow_attachments_ids = fields.One2many(related="sb_workflow_id.sb_workflow_attachments_ids",
                                                  string="Approval Attachments")
    sb_workflow_ids = fields.One2many('sb.workflow', 'stock_picking_id', string="Approval Workflows")
    sb_workflow_ids_sum = fields.Integer(compute="_compute_sb_workflow_ids_sum", store=True)
    sb_is_quality_check = fields.Boolean(default=False, compute="_compute_quality_check", store=True)
    sb_loss_approve = fields.Boolean(default=False, compute="_compute_quality_check", store=True)
    sb_rework_check_id = fields.Many2one('s.rework.check', string='检修')

    # 不用了=====
    sb_expiration_date = fields.Datetime(string='Expiration Date')
    sb_required_iqc = fields.Boolean(string="IQC", default=False, compute='_compute_sb_required_iqc')
    # ========

    def _cron_quality_check(self):
        """每日执行一次，自动生成临期质检调拨"""
        # 临期质检作业
        picking_type = self.env.ref('sb_quality_check.picking_type_expired_quality')
        location_dest_id = self.env.ref('sb_quality_check.location_quality_check')

        # 生产前位置不需要质检
        production_location = self.env['stock.location'].search([('barcode', '=', 'WH-PREPRODUCTION')])
        plids = production_location.child_ids.ids

        quality_lots = self.env['stock.lot'].sudo().search([('product_qty', '>', 0), ('alert_date', '!=', False)]).filtered(lambda x: fields.Datetime.now() > x.alert_date)
        quants = quality_lots.mapped('quant_ids').filtered(lambda x: x.location_id.usage == 'internal' and x.location_id.id not in plids and x.inventory_quantity_auto_apply > 0 and x.location_id != location_dest_id)

        # 1 查询是否存在临期质检调拨没有完成的
        check_picking_ids = self.sudo().search([('picking_type_id', '=', picking_type.id), ('state', 'not in', ['done', 'cancel']), ('location_dest_id', '=', location_dest_id.id)])
        check_lot_ids = check_picking_ids.mapped('move_ids').mapped('lot_ids')

        # 2 查询是质检完成，调回原位置没有完成的调拨
        r_check_picking_ids = self.sudo().search([('picking_type_id', '=', picking_type.id), ('state', 'not in', ['done', 'cancel']), ('location_id', '=', location_dest_id.id)])
        r_check_lot_ids = r_check_picking_ids.mapped('move_ids').mapped('lot_ids')

        # 3 查询质检完成，但没有完成的报废调拨,
        # 质检报废作业
        s_picking_type = self.env.ref('sb_quality_check.picking_type_expired_scrap_quality')
        scrap_location_dest_id = self.env['stock.location'].sudo().search([('name', '=', 'Scrap')], limit=1)
        if not location_dest_id:
            scrap_location_dest_id = self.env['stock.location'].sudo().browse(16)
        s_check_picking_ids = self.sudo().search([('picking_type_id', '=', s_picking_type.id), ('state', 'not in', ['done', 'cancel']),('location_dest_id', '=', scrap_location_dest_id.id)])
        s_check_lot_ids = s_check_picking_ids.mapped('move_ids').mapped('lot_ids')
        lot_ids = check_lot_ids | r_check_lot_ids | s_check_lot_ids
        for quant in quants:
            if quant.lot_id in lot_ids:
                continue
            lot = quant.lot_id
            picking_vals = {
                'name': picking_type.sequence_id.next_by_id(),
                'picking_type_id': picking_type.id,
                'location_id': quant.location_id.id,
                'location_dest_id': location_dest_id.id,
                'scheduled_date': fields.Datetime.now(),
                'move_ids': [(0, 0, self._get_move_vals(lot, picking_type, quant))],
            }
            picking = self.create(picking_vals)
            picking.action_confirm()

        if lot_ids or 'picking' in locals() and picking:
            # 发送用户通知
            message = '存在带完成的临期质检作业，请尽快完成。'
            # groups="stock.group_stock_manager,stock.group_stock_user"
            self.env['mail.message'].sudo().post_message_to_group_user('sb_quality_check.group_quality_check_message_user', message)

    def _get_move_vals(self, lot, picking_type, quant):
        return {
            'company_id': self.env.user.company_id.id,
            'date': datetime.now(),
            'location_id': quant.location_id.id,
            'location_dest_id': picking_type.default_location_dest_id.id,
            'product_id': quant.product_id.id,
            'name': quant.product_id.display_name,
            'procure_method': 'make_to_stock',
            'product_uom': quant.product_uom_id.id,
            'product_uom_qty': quant.inventory_quantity_auto_apply,
            'lot_ids': [(0, 0, [lot.id])],
            'move_line_ids': [(0, 0, {
                'product_id': quant.product_id.id,
                'lot_id': lot.id,
                'quantity': quant.inventory_quantity_auto_apply,
                'quant_id': quant.id,
                'location_id': quant.location_id.id,
                'location_dest_id': self.env.ref('sb_quality_check.location_quality_check').id,
            })]
        }

    # 生成审批流
    def create_workflow(self):
        if self.sb_workflow_template_id:
            if len(self.sb_workflow_ids) > 0:
                workflow_sum = len(self.sb_workflow_ids) + 1
            else:
                workflow_sum = 1
            # 创建审批流
            new_wf_id = self.env['sb.workflow'].sudo().create({
                'name': self.name + '-Approval Workflow' + '-' + str(workflow_sum),
                'approval_time': fields.Datetime.now(),
                'workflow_type': 'stock_picking',
                'stock_picking_id': self.id,
            })
            self.sb_workflow_id = new_wf_id.id
            # 根据模板生成审批项
            item_audit_levels = []
            for item in self.sb_workflow_template_id.sb_workflow_template_item_ids:
                new_item = self.env['sb.workflow.item'].sudo().create({
                    'name': item.name,
                    'user_group_ids': item.user_group_ids.ids,
                    'audit_level': item.audit_level,
                    'sb_workflow_id': new_wf_id.id,
                    'state': 'wait_forward'
                })
                # 收集生成的审核项的所有层级
                item_audit_levels.append(new_item.audit_level)
            # 去重排序
            item_audit_levels = list(set(item_audit_levels))
            item_audit_levels.sort()
            # 开放最低层级的神匹配
            for n_item in new_wf_id.sb_workflow_item_ids:
                if n_item.audit_level == item_audit_levels[0]:
                    n_item.state = 'approval'
        else:
            raise ValidationError(_('Please select an approval template'))

    def _check_for_quality_checks(self):
        return self.env['stock.picking']

    def button_validate(self):
        if self.sb_workflow_state != 'approve' and self.sb_loss_approve:
            raise ValidationError(_('请先发起审批或等待审批通过后再进行验证！'))

        # if self.sb_required_iqc:
        #     raise ValidationError(_('原材料入库需要质检，请先发送质检通知！'))
        # elif self.check_ids.filtered(lambda x: x.quality_state != 'pass'):
        #     raise ValidationError(_('原材料入库需要质检，请通知IQC质检完成后再入库！'))
        res = super(StockPicking, self).button_validate()

        # 生成临期质检单，正向调拨
        if self.filtered(lambda x: x.picking_type_id.barcode == 'WTT-EQ' and x.location_dest_id == self.env.ref('sb_quality_check.location_quality_check')):
            for move in self.move_ids:
                check_vals = {
                    'product_id': move.product_id.id,
                    'measure_on': 'move_line',
                    's_check_type': 'expired_quality',
                    'lot_id': move.lot_ids[0].id,
                    'picking_id': self.id,
                    'team_id': self.env.ref('sb_quality_check.quality_alert_qc_team0').id,
                    's_product_qty': move.quantity,
                    'test_type_id': self.env.ref('quality_control.test_type_passfail').id,
                    's_readonly': True
                }
                self.env['quality.check'].create(check_vals)

        # # 生成临期质检单，反向调拨入库。校验入库数量、以及批次
        if self.origin and self.picking_type_id.barcode == 'WTT-EQ' and self.location_id == self.env.ref('sb_quality_check.location_quality_check'):
            quality_check_id = self.env['quality.check'].sudo().search([('name', '=', self.origin)], limit=1)
            goods_qty = quality_check_id.s_good_product_qty
            for m in self.move_ids:
                if float_compare(m.quantity, goods_qty, m.product_uom.rounding) == 1:
                    raise ValidationError('最大入库数不能超过，质检良品数: 【{}】'.format(goods_qty))
                if m.lot_ids != quality_check_id.lot_id:
                    raise ValidationError('临期质检不运行修改指定批次号。')
        return res

    def action_message(self):
        self.ensure_one()
        for move in self.move_ids:
            if not move.product_id.s_required_iqc:
                continue

            for line in move.move_line_ids:
                if not line.lot_id and not line.lot_name:
                    raise UserError(_('Product (%s) , Please fill in the batch in the notification for quality inspection!', move.product_id.name))
                check_vals = {
                    'product_id': move.product_id.id,
                    'measure_on': 'product',
                    's_check_type': 'iqc',
                    'picking_id': self.id,
                    'team_id': 2,  # 来料检验
                    's_product_qty': line.quantity,
                    'test_type_id': self.env.ref('quality_control.test_type_passfail').id,
                    's_readonly': True,
                    'move_id': move.id,
                    'move_line_id': line.id,
                    # 'lot_name': line.lot_id.name or line.lot_name
                }
                quality_check = self.env['quality.check'].create(check_vals)
                # 发送用户通知
                message = _('Product: %s, Lot: %s, Order: %s, Incoming materials require quality inspection', move.product_id.name, line.lot_id.name or line.lot_name, quality_check.name)
                # groups="stock.group_stock_manager,stock.group_stock_user"
                self.env['mail.message'].sudo().post_message_to_group_user('sb_quality_check.group_quality_check_message_user', message)
